package com.thinvent.recommend.manager.lucene;

import com.huaban.analysis.jieba.JiebaSegmenter;
import com.huaban.analysis.jieba.SegToken;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.Tokenizer;
import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;

import java.io.IOException;
import java.io.Reader;
import java.util.Iterator;
import java.util.List;

/**
 * 自定义 Lucene Analyzer，内部使用 JiebaSegmenter 分词
 * 手动将 Reader 读成 String，避免 IOUtils 版本不匹配的问题
 */
public class JiebaAnalyzer extends Analyzer {

    private final JiebaSegmenter segmenter = new JiebaSegmenter();

    @Override
    protected TokenStreamComponents createComponents(String fieldName) {
        Tokenizer tokenizer = new JiebaTokenizer(segmenter);
        return new TokenStreamComponents(tokenizer);
    }

    private static class JiebaTokenizer extends Tokenizer {
        private final JiebaSegmenter segmenter;
        private Iterator<SegToken> iter;
        private final CharTermAttribute termAttr = addAttribute(CharTermAttribute.class);

        public JiebaTokenizer(JiebaSegmenter segmenter) {
            this.segmenter = segmenter;
        }

        @Override
        public boolean incrementToken() throws IOException {
            clearAttributes();
            if (iter != null && iter.hasNext()) {
                SegToken token = iter.next();
                String word = token.word;
                termAttr.append(word);
                termAttr.setLength(word.length());
                return true;
            }
            return false;
        }

        @Override
        public void reset() throws IOException {
            super.reset();
            // 1. 手动将整个 Reader 读成字符串
            String text = readToString(input);
            // 2. 用 Jieba 搜索模式分词
            List<SegToken> tokens = segmenter.process(text, JiebaSegmenter.SegMode.SEARCH);
            this.iter = tokens.iterator();
        }

        /**
         * 将 Reader 内容全部读入为 String
         */
        private String readToString(Reader reader) throws IOException {
            char[] buffer = new char[4096];
            int len;
            StringBuilder sb = new StringBuilder();
            while ((len = reader.read(buffer)) != -1) {
                sb.append(buffer, 0, len);
            }
            return sb.toString();
        }
    }
}
